`include "ascon_define.v"

module `RX_BUF_4_32B_64
    (
    input                                        clk_i,
    input                                        rstn_i,

    input                                        en_i,
    input                                        wen_i,
    input                  [`AHB_BUS_ADDR_W-1:0] waddr_i,
    input                  [`AHB_BUS_DATA_W-1:0] wdata_i,
    input                                        mode_i,

    input                    [`BUF_ADDR_W+1-1:0] raddr_i,
    output                            [`P_W-1:0] rdata_o
    );

reg                                              wen_0  , wen_1 , wen_2  , wen_3  ;
reg                                              en_0  , en_1 , en_2  , en_3  ;
wire                       [`AHB_BUS_DATA_W-1:0] wdata_0, wdata_1, wdata_2, wdata_3;
wire                       [`AHB_BUS_DATA_W-1:0] rdata_0, rdata_1, rdata_2, rdata_3;

wire                                  [`P_W-1:0] n_rdata_w;
wire                                  [`P_W-1:0] a_rdata_w;
wire                                       [1:0] wByte_sel;
wire                           [`BUF_ADDR_W-1:0] waddr;

wire                                       [0:0] rByte_sel;
wire                           [`BUF_ADDR_W-1:0] raddr;



assign waddr            = waddr_i[4+`BUF_ADDR_W-1:4];
assign wByte_sel        = waddr_i[3:2];

assign raddr            = raddr_i[`BUF_ADDR_W:1];
assign rByte_sel        = raddr_i[0:0];

always@(*)
begin : WEN_X_PROG
  case (wByte_sel)
    2'b00 : begin
      wen_0             = wen_i;
      wen_1             = 1'b0;
      wen_2             = 1'b0;
      wen_3             = 1'b0;
    end
    2'b01 : begin
      wen_0             = 1'b0;
      wen_1             = wen_i;
      wen_2             = 1'b0;
      wen_3             = 1'b0;
    end
    2'b10 : begin
      wen_0             = 1'b0;
      wen_1             = 1'b0;
      wen_2             = wen_i;
      wen_3             = 1'b0;
    end
    2'b11 : begin
      wen_0             = 1'b0;
      wen_1             = 1'b0;
      wen_2             = 1'b0;
      wen_3             = wen_i;
    end
    default: begin
      wen_0             = 1'b0;
      wen_1             = 1'b0;
      wen_2             = 1'b0;
      wen_3             = 1'b0;
    end
  endcase
end

always@(*)
begin : EN_X_PROG
  case (wByte_sel)
    2'b00 : begin
      en_0              = en_i;
      en_1              = 1'b0;
      en_2              = 1'b0;
      en_3              = 1'b0;
    end
    2'b01 : begin
      en_0              = 1'b0;
      en_1              = en_i;
      en_2              = 1'b0;
      en_3              = 1'b0;
    end
    2'b10 : begin
      en_0              = 1'b0;
      en_1              = 1'b0;
      en_2              = en_i;
      en_3              = 1'b0;
    end
    2'b11 : begin
      en_0              = 1'b0;
      en_1              = 1'b0;
      en_2              = 1'b0;
      en_3              = en_i;
    end
    default: begin
      en_0              = 1'b0;
      en_1              = 1'b0;
      en_2              = 1'b0;
      en_3              = 1'b0;
    end
  endcase
end

// 小端存储
assign wdata_0          = wdata_i;
assign wdata_1          = wdata_i;
assign wdata_2          = wdata_i;
assign wdata_3          = wdata_i;

// 输出读数据选通
assign n_rdata_w        = (rByte_sel == 1'b0) ? {rdata_1,rdata_0,64'b0} : {rdata_3,rdata_2,64'b0};
assign a_rdata_w        = {rdata_3,rdata_2,rdata_1,rdata_0};
assign rdata_o          = (mode_i == 1'b0) ? a_rdata_w : n_rdata_w;

// 第一字
`RAM_32B_64
u_ram_0(
    .clk_i                             (clk_i                                  ),
    .rstn_i                            (rstn_i                                 ),

    .en_i                              (en_0                                   ),
    .wen_i                             (wen_0                                  ),
    .waddr_i                           (waddr                                  ),
    .wdata_i                           (wdata_0                                ),

    .raddr_i                           (raddr                                  ),
    .rdata_o                           (rdata_0                                )
);

// 第二字
`RAM_32B_64
u_ram_1
(
    .clk_i                             (clk_i                                  ),
    .rstn_i                            (rstn_i                                 ),

    .en_i                              (en_1                                   ),
    .wen_i                             (wen_1                                  ),
    .waddr_i                           (waddr                                  ),
    .wdata_i                           (wdata_1                                ),

    .raddr_i                           (raddr                                  ),
    .rdata_o                           (rdata_1                                )
);

// 第三字
`RAM_32B_64
u_ram_2(
    .clk_i                             (clk_i                                  ),
    .rstn_i                            (rstn_i                                 ),

    .en_i                              (en_2                                   ),
    .wen_i                             (wen_2                                  ),
    .waddr_i                           (waddr                                  ),
    .wdata_i                           (wdata_2                                ),

    .raddr_i                           (raddr                                  ),
    .rdata_o                           (rdata_2                                )
);

// 第四字
`RAM_32B_64
u_ram_3
(
    .clk_i                             (clk_i                                  ),
    .rstn_i                            (rstn_i                                 ),

    .en_i                              (en_3                                   ),
    .wen_i                             (wen_3                                  ),
    .waddr_i                           (waddr                                  ),
    .wdata_i                           (wdata_3                                ),

    .raddr_i                           (raddr                                  ),
    .rdata_o                           (rdata_3                                )
);


endmodule